<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1,maximum-scale=1" name="viewport">
<title>Experiment: Infinite Scroll with Blogger JSON</title>
<link rel="shortcut icon" href="http://mini-web-tools.googlecode.com/svn/p/img/favicon.ico">






<!--

Author: Taufik Nurrohman
Author URL: http://www.dte.web.id (http://hompimpaalaihumgambreng.blogspot.com)
Author G+: https://plus.google.com/108949996304093815163/about

You are allowed to learn, use, add a new attribution/making your own attribution or modify my works in this page as long as you don't:

1. Making copies of this work for distribution without a clear attribution of the author.
2. Making copies of this work for commercial purpose.
3. Removing this rules & attribution with or without permission.
4. Distributing your work that's created based on this work for commercial purpose.

-->






<style type="text/css">

* {
  margin:0;
  padding:0;
}

html {
  overflow-y:scroll;
}

body {
  background-color:#eee;
}





/* Default Infinite Scroll Stylesheet */
.blog-post-list {
  width:800px;
  margin:90px auto 50px;
  font:normal normal 13px/1.4 Arial,Sans-Serif;
  color:#333;
}

.blog-post-list a {
  color:#2B7EB6;
  text-decoration:none;
}

.blog-post-list a:hover {
  color:#2C6289;
  text-decoration:underline;
}

.blog-post-list a img {
  border:none;
}

.blog-post-list h1,
.blog-post-list h2,
.blog-post-list h3,
.blog-post-list h4,
.blog-post-list h5,
.blog-post-list h6 {
  font-weight:bold;
  line-height:normal;
  margin:2em 0 1.5em;
  letter-spacing:-1px;
}

.blog-post-list h1 {font-size:200%}
.blog-post-list h2 {font-size:180%}
.blog-post-list h3 {font-size:140%}
.blog-post-list h4 {font-size:120%}
.blog-post-list h5 {font-size:100%}
.blog-post-list h6 {font-size:80%}

.blog-post-list p,
.blog-post-list pre,
.blog-post-list table,
.blog-post-list blockquote,
.blog-post-list figure,
.blog-post-list hr,
.blog-post-list ol,
.blog-post-list ul {margin:1.5em 0}

.blog-post-list ol,
.blog-post-list ul {margin-left:2em}

.blog-header {
  text-transform:uppercase;
  position:fixed;
  top:0;
  right:0;
  left:0;
  z-index:9999;
  background-color:white;
  -webkit-box-shadow:0 1px 7px -1px rgba(0,0,0,.4);
  -moz-box-shadow:0 1px 7px -1px rgba(0,0,0,.4);
  box-shadow:0 1px 7px -1px rgba(0,0,0,.4);
}

.blog-header h1 {
  margin:0 0;
  font:normal bold 110%/100% "Arial Narrow",Arial,Sans-Serif;
  padding:1em;
  letter-spacing:0;
}

.blog-header .blog-navigation {
  display:block;
  height:30px;
  line-height:30px;
  padding:0 1em;
  background-color:#333;
  font-size:86%;
}

.blog-header .blog-navigation a {
  color:white;
  font-weight:bold;
}

.blog-post-list .blog-post {
  background-color:white;
  border:1px solid #ccc;
  padding:1em 1.4em;
  margin:0 auto 1em;
}

.blog-post-list .blog-post-title {
  margin-top:0;
  margin-bottom:.2em;
}

.blog-post-list .blog-post-published {
  display:block;
  margin:0 0 3em;
  color:#aaa;
  font-weight:bold;
}

.blog-post-list .comment-section {
  margin:3em 0 0;
  padding:.5em .5em 0;
  border-top:1px solid #ccc;
}

.blog-post-list .comment-section ol {
  margin:.5em 0;
}

.blog-post-list .comment-section li {
  padding:.5em;
  list-style:none;
  margin:0 0 2px;
  background-color:#f5f5f5;
  overflow:hidden;
  clear:both;
}

.blog-post-list .comment-section .blog-post-comment-avatar {
  float:left;
}

.blog-post-list .comment-section .blog-post-comment-item {
  margin-left:46px;
}

.comment-section .blog-post-comment-comment-item-published {
  display:block;
  font-style:italic;
  font-size:86%;
  color:#999;
  text-align:right;
}

.blog-post-list .comment-section .blog-post-comment-form {
  clear:both;
  width:100%;
  border:none;
  background:none;
  height:280px;
  overflow:hidden;
  margin:2em 0 0;
}

.blog-post-list code {
  font-family:Consolas,"Courier New",Courier,Monospace;
}

.blog-post-list pre {
  overflow:auto;
  white-space:pre;
  word-wrap:normal;
  background-color:#333;
  padding:1em 1.2em;
  font-family:Consolas,"Courier New",Courier,Monospace;
  font-size:12px;
  color:#ddd;
}

.blog-post-list pre code {
  font:inherit;
  color:inherit;
}

.blog-post-list blockquote {
  font-style:italic;
  color:#666;
  border-left:4px solid #ccc;
  padding:0 1em;
  margin-left:2em;
}

.blog-post-list table[border="1"] {
  border-collapse:collapse;
  width:100%;
}

.blog-post-list table[border="1"] th,
.blog-post-list table[border="1"] td {
  vertical-align:top;
  text-align:left;
  border:1px solid;
  padding:.5em 1em;
}

.feed-loading-indicator {
  width:100px;
  height:30px;
  text-align:center;
  font:normal bold 13px/30px Arial,Sans-Serif;
  color:#ddd;
  background-color:#333;
  position:fixed;
  bottom:0;
  left:50%;
  margin-left:-50px;
  z-index:9999;
  -webkit-transition:bottom .2s ease-out;
  -moz-transition:bottom .2s ease-out;
  -ms-transition:bottom .2s ease-out;
  -o-transition:bottom .2s ease-out;
  transition:bottom .2s ease-out;
}

.clear {
  display:block;
  clear:both;
}

@media (max-width:850px) {
  .blog-post-list {width:96%}
  .blog-post-list img {
    max-width:98%;
    height:auto !important;
  }
}

@media (max-width:350px) {
  .blog-post-list {font-size:11px}
  .blog-post-list pre {font-size:100%}
}





/* Custom CSS for My Blog Design */
.message {
  margin:90px auto -70px;
  padding:1em;
  width:600px;
  border:1px solid #FFA798;
  background-color:#FFFFAA;
  font:normal normal 11px/1.2 Tahoma,Verdana,Arial,Sans-Serif;
  color:#444;
}

.center,
.button-group {
  display:block;
  margin-left:auto;
  margin-right:auto;
  text-align:center;
}

.alignleft,
.align-left {
  float:left;
  margin:0 2em .5em 0;
}

.alignright,
.align-right {
  float:right;
  margin:0 0 .5em 2em;
}

iframe.jsfiddle-demo {
  display:block;
  width:90%;
  height:240px;
  border:2px solid black;
}

.center,
iframe.jsfiddle-demo {
  margin:1.5em auto;
}

.button-group .button,
.button-group .button:hover {
  background-color:#2B7EB6;
  color:white;
  font-weight:bold;
  font-size:86%;
  padding:.5em 1em;
  line-height:3em;
  text-decoration:none;
}

.button-group .button:hover {
  background-color:#2C6289;
}

@media (max-width:850px) {
  .message {width:80%}
}

</style>
</head>
<body>




<!-- Just a message -->
<div class="message"><p>Hello&hellip; This page demonstrates how I use <code>removeChild()</code> and <code>.appendChild()</code> to remove and update the JSON callback script when the screen scrolls have reached to the end.</p><p>By the way, this page will continue to load up on the last post. I hope you don't use this page as a fast reading media for my blog posts. Visit <a href="http://www.dte.web.id" title="DTE :]">the original blog</a> and read the articles through the original blog post to support the development of my blog. Thank you very much.</p></div>
<!-- End message -->






<div id="blog-post-list" class="blog-post-list">
	<div class="blog-header">
		<h1><a href="http://www.dte.web.id">Feeds From DTE :]</a></h1>
		<span class="blog-navigation"><a href="http://www.dte.web.id/2013/03/infinite-scroll-experiment-with-blogger.html">Home</a></span>
	</div>
	<div id="blog-content" class="blog-content"></div>
</div>
<div id="feed-loading-indicator" class="feed-loading-indicator"></div>


<script type="text/javascript">

// Widget config start
var infiniteScroll = {
	url: 'http://www.dte.web.id',
	numpost: 3,
	containerId: 'blog-content',
	loader: 'feed-loading-indicator',
	scriptId: 'json-script',
	labels: {
		postComment: 'Post a Comment',
		noComment: 'No Comment',
		loadingText: 'Loading...',
		monthNames: ["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"]
	}
};
// Config end.

var init = 1, // First visit = true
	index = 0,
	loaded = true,
	postNum = 0,
	dynamicId = null,
	commentFormUrl = "",
	container = document.getElementById(infiniteScroll.containerId),
	loader = document.getElementById(infiniteScroll.loader);
	
loader.innerHTML = infiniteScroll.labels.loadingText;

// SCRIPT FOR LOADING THE BLOG POSTS
function loadPosts(json) {

	var handleDiv = document.createElement('div'),
		entry = json.feed.entry,
		skeleton = "",
		date, content, link, commentNum, commentFeed, formUrl;

	for (var i = 0; i < infiniteScroll.numpost; i++) {

		postNum = postNum + infiniteScroll.numpost;

		for (var j = 0, jen = entry[i].link.length; j < jen; j++) {
			if (entry[i].link[j].rel == "alternate") {
				link = entry[i].link[j].href;
				break;
			}
		}
		for (var k = 0, ken = entry[i].link.length; k < ken; k++) {
			if (entry[i].link[k].rel == "replies" && entry[i].link[k].type == "application/atom+xml") {
				commentFeed = entry[i].link[k].href;
				break;
			}
		}
		for (var l = 0, len = entry[i].link.length; l < len; l++) {
			if (entry[i].link[l].rel == "replies" && entry[i].link[l].type == "text/html") {
				commentNum = entry[i].link[l].title;
				break;
			}
		}

		date = entry[i].published.$t.substring(0,10).split('-');
		content = ("content" in entry[i]) ? entry[i].content.$t : "";

		formUrl = entry[i].id.$t.replace(/^(.*?)blog-(.*?)\.post-(.*?)$/,"http://www.blogger.com/comment-iframe.g?blogID=$2&postID=$3");

		// This private regex is created just to handle my blog post markup pattern
		// Ignore/remove this if you want to develop all of this script
		content = content.replace(/<div class="jsfiddle-demo(.*?)data-src="(.*?)"(.*?)div>/ig,"<iframe src=\"$2\" class=\"jsfiddle-demo\"></iframe>").replace(/ href="\//g," href=\"" + infiniteScroll.url + "/");
		content = content.replace(/<code class="(.*?)">(.[\w\W\n]+?)<\/code>/ig, function(m) {
			return m.replace(/\.(.*?)\(/g,".<span style='color:#666;'>[cencored]</span>(").replace(/(&lt;|&gt;)/ig,"<span style='color:#666;'>[this way]</span>").replace(/^/g,"<em>[Some code snippet just removed and [cencored]\nin order to make sure you not just read my blog post\nfrom this experiment page.\nPlease visit the original blog post <a title='Read more...' href='" + link + "'>here</a>]</em>\n\n");
		});
		// End private regex

		skeleton += '<div class="blog-post">';
		skeleton += '<h2 class="blog-post-title"><a href="' + link + '" title="Read the original blog post">' + entry[i].title.$t + '</a></h2>';
		skeleton += '<time class="blog-post-published" datetime="' + date.join('-') + '">' + date[2] + ' ' + infiniteScroll.labels.monthNames[(parseInt(date[1],10)-1)] + ' ' + date[0] + '</time>';
		skeleton += '<div class="blog-post-body">' + content + '</div>';
		skeleton += '<div class="comment-section" id="comment-' + postNum + '"><a title="Show comments" href="#comment-' + postNum + '" onclick="loadJSON(\'' + commentFeed + '?alt=json-in-script&reverse=false&callback=loadPostComments\', \'comment-' + postNum + '\');commentFormUrl=\'' + formUrl + '\';return false;">' + commentNum + '</a></div>';
		skeleton += '</div>';

	}

	handleDiv.innerHTML = skeleton;
	container.appendChild(handleDiv);

	setTimeout(function() {
		loader.style.bottom = '-30px';
		loaded = true;
	}, 500);

}

// SCRIPT FOR LOADING THE COMMENTS
function loadPostComments(json) {
	var entry = json.feed.entry,
		content, avatar, author, commentator, published, isopub, deleteUri,
		skeleton = "";
	if (typeof entry !== "undefined") {

		skeleton = '<ol>';

		for (var i = 0, len = entry.length; i < len; i++) {

			content = ("content" in entry[i]) ? entry[i].content.$t : "";
			author = entry[i].author[0].name.$t;
			commentator = (entry[i].author) ? '<a href="' + entry[i].author[0].uri.$t + '">' + author + '</a>' : author;
			avatar = entry[i].author[0].gd$image.src.replace(/\/s\d+(\-c)?\//,"/s36-c/").replace(/http\:/,"");
			published = entry[i].gd$extendedProperty[1].value;
			isopub = entry[i].published.$t;
			deleteUri = entry[i]["thr$in-reply-to"].ref.replace(/^(.*?)blog-(.*?)\.post-(.*?)$/,"http://www.blogger.com/delete-comment.g?blogID=$2&postID=$3");;

			skeleton += '<li><div class="blog-post-comment-avatar"><img width="36" height="36" src="http:' + avatar + '" alt="' + author + '"></div><div class="blog-post-comment-item"><strong>' + commentator + ':</strong> ' + content + ' <span class="clear"></span><time class="blog-post-comment-comment-item-published" datetime="' + isopub + '" title="' + isopub + '">' + published + '</time></div></li>';

		}

		skeleton += '</ol>';

	} else {
		skeleton = '<div>' + infiniteScroll.labels.noComment + '</div>';
	}
	skeleton += '<iframe class="blog-post-comment-form" frameborder="0" src="' + commentFormUrl + '"></iframe>';

	document.getElementById(dynamicId).innerHTML = skeleton;
	loaded = true;
}

// SCRIPT FOR APPEND/REMOVE THE ASYNCHRONOUS CALLBACK SCRIPT WITH SOME LOGIC PARAMETERS
function loadJSON(url, loadTo) {
	dynamicId = loadTo;
	var feedUrl = (url !== null) ? url : infiniteScroll.url + '/feeds/posts/default?alt=json-in-script&max-results=' + infiniteScroll.numpost + '&start-index=' + ((init == 1) ? 1 : (infiniteScroll.numpost*index)+1) + '&callback=loadPosts';
	if (loaded === true) {
		var script = document.createElement('script');
			script.type = "text/javascript";
			script.id = infiniteScroll.scriptId;
			script.src = feedUrl;
		if (document.getElementById(infiniteScroll.scriptId)) {
			var old = document.getElementById(infiniteScroll.scriptId);
			old.parentNode.removeChild(old);
			if (loadTo === null) {
				loader.style.bottom = '0';
			} else {
				document.getElementById(dynamicId).innerHTML = infiniteScroll.labels.loadingText;
			}
		}
		document.documentElement.firstChild.appendChild(script);
		loaded = false;
	}
	init = 0; // First visit = false
}

// WINDOW SCROLL EVENT: CHECK IF WE HAVE REACHED THE END
window.onscroll = function() {
    if (navigator.userAgent.toLowerCase().indexOf("chrome") > -1 || navigator.userAgent.toLowerCase().indexOf("safari") > -1) {
        if (document.documentElement.scrollHeight == (document.body.scrollTop + document.documentElement.clientHeight)) {
			index++;
			loadJSON(null, null); // Update the callback script if we have reached end of the page
        }
    } else {
        if (document.documentElement.scrollHeight == (document.documentElement.scrollTop + document.documentElement.clientHeight)) {
			index++;
            loadJSON(null, null); // Update the callback script if we have reached end of the page
        }
    }
};

// Initiation
loadJSON(null, null);

</script>

</body>
</html>